package p2tokenstream;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;

import java.io.IOException;
import java.io.StringReader;

/**
 * 二：
 *
 * TokenStream 是经过分词器处理后得到的一个流，里面存有各种信息
 *
 * Tokenizer 主要负责接收 Reader,将reader 进行分词操作
 * tokenStream有很多的 Attribute 列如下面的 CharTermAttribute 等
 */
public class TokenAttributeUtils {
    public static void displayToken(String str, Analyzer a) throws IOException {
        TokenStream stream=a.tokenStream("content",new StringReader(str));
        CharTermAttribute car=stream.addAttribute(CharTermAttribute.class);
        //当
        while (stream.incrementToken()){
            System.out.print("["+car+"]");
        }
        System.out.println();
        System.out.println("======================");
    }

    /**
     *当我们向 readder 中传入一个查询字符串的时候，比如"how are you",
     * 会经过TokenStream的转化，TokenStream有两个实现类，
     * Tokenizer 和 TokenFilter
     *
     * 1，Tokenizer:将一个字符串 划分为不同的语汇单元
     *
     * Tokenizer 有多个实现类 ：
     * （1） KeywordTokenizer(不进行分词，传的是什么就是什么)
     * （2）StandardTokenizer(标准分词器，有些智能的分词功能，比如 majian@sina.com,会把 sina.com 作为一个分词)
     * （3）CharTokenizer(针对字符进行分词，他又又两个实现类，
     * WhiteSpaceTokenizer:只要又空格就进行分词，比如 how are you,会分词为 how,are,you)
     * LetterTokenizer:
     *
     * 2,TokenFilter：对划分的语汇单元进行过滤，（比如过滤掉一些停用词） 又很多实现类比如
     * （1）StopFilter:停用词过滤
     * （2）LowCaseFilter: 都换成小写
     * （3）StandFilter:
     * (4)PorterFilter: 会把一些时态，语态词还原，比如 coming 会还原成 come 等
     *
     *
     * 总结：大致流程就是reader --> Tokenizer(拆分语汇单元)---> N 个 TokenFilter(经过N个tokenfilter 进行包装，过滤)
     * ---> 然后最终得到 TokenStream 数据流
     *
     *################################################
     *
     * ##### TokenAttribute ####
     *
     * 总结：对于上面经过分词和过滤后的词，形成 TokenStram, 那么如何来保存这些词呢,和这些词的额外的一些信息呢？以下就是
     * 在创建索引的时候 比如 how are you ,会给分词成how,are,you,lucene 怎么来保存这些词呢
     * 首先会通过 CharTermAttribute 保存每一个词汇，
     *
     * 其次保存顺序，顺序是以增量来保存的 比如 how 开始0，结束3 [0,3] are[4,7],you[8,11] 是用
     * OffsetAttribute 来保存各个 词之间的偏移量的
     *
     * 还有要保存 两个词直接的距离，默认1 ，比如 how 和are 距离是1，are和you距离是1，how 和you 距离是2通过
     * PositionIncrementAttribute 来保存
     *
     *
     * 比如假如我们保存的文本是 how are you ,,, how 的位置是1，假如有一个词this 位置也是1，那我们搜索this的时候也能
     * 搜索出来，利用这个特性可以做同义词（还不是太清楚这块）
     *
     */
    //上个是获取分词后词信息，这个是获取分词后位置信息，和偏移量信息
    public static void displayAllTokenInfo(String str, Analyzer a) throws IOException {
        TokenStream stream=a.tokenStream("content",new StringReader(str));
        //位置
        PositionIncrementAttribute pia=stream.addAttribute(PositionIncrementAttribute.class);
        //偏移量
        OffsetAttribute oa=stream.addAttribute(OffsetAttribute.class);
        //分词后的每个词
        CharTermAttribute cta=stream.addAttribute(CharTermAttribute.class);
        //类型信息，对于标准分词器，分词后，默认的类型是”word“,我们定义自己分词器的时候可以定义
        //自己的类型信息，然后我们处理的时候可以看这个类型是不是自己定义的，是自己定义的话
        //我们可以做一些额外处理
        TypeAttribute ta=stream.addAttribute(TypeAttribute.class);
        for(;stream.incrementToken();){
            System.out.print(pia.getPositionIncrement()+":");
            System.out.println(cta+"["+oa.startOffset()+"-"+oa.endOffset()+"]"+"--->"+ta.type());
            System.out.println(cta);
        }
        System.out.println("##########################");
    }
}
